package com.cds.drizzt.exception;


import com.cds.drizzt.entity.JsonResult;
import com.cds.drizzt.utils.enums.HttpCodeEnum;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

/**
 * 全局异常处理器：统一捕获并处理所有异常，返回 JsonResult 格式响应
 */
@Slf4j
@RestControllerAdvice // 作用于所有 @RestController，自动返回 JSON
public class GlobalExceptionHandler {

    // -------------------------- 1. 处理自定义业务异常（核心场景） --------------------------
    @ExceptionHandler(BusinessException.class)
    public JsonResult<Void> handleBusinessException(BusinessException e, HttpServletRequest request) {
        // 从业务异常中获取 HttpCodeEnum（假设 BusinessException 有 getHttpCodeEnum() 方法）
        HttpCodeEnum httpCodeEnum = e.getHttpCodeEnum();
        String requestInfo = String.format("[%s %s]", request.getMethod(), request.getRequestURI());

        // 业务异常日志（WARN级别，记录关键信息，无需堆栈）
        log.warn("业务异常 {}: 错误码={}, 消息={}", requestInfo, httpCodeEnum.getCode(), e.getMessage());

        // 返回统一响应结果（使用枚举的错误码和异常消息）
        return JsonResult.error(httpCodeEnum.getCode(), e.getMessage());
    }

    // -------------------------- 2. 处理参数校验异常（@Valid 触发） --------------------------
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST) // HTTP 状态码 400
    public JsonResult<Void> handleValidationException(MethodArgumentNotValidException e) {
        // 提取校验失败的字段提示信息（如 @NotBlank(message = "用户名不能为空")）
        String errorMsg = e.getBindingResult().getFieldError().getDefaultMessage();
        log.warn("参数校验失败: {}", errorMsg);

        // 使用枚举中的 "参数错误" 编码（假设 HttpCodeEnum 有 PARAM_ERROR 常量）
        return JsonResult.error(HttpCodeEnum.RC400.getCode(), errorMsg);
    }

    // -------------------------- 3. 处理 404 资源不存在异常 --------------------------
    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND) // HTTP 状态码 404
    public JsonResult<Void> handle404Exception(NoHandlerFoundException e) {
        log.warn("资源不存在: 请求路径={}", e.getRequestURL());
        // 使用枚举中的 "资源不存在" 编码（假设 HttpCodeEnum 有 RESOURCE_NOT_FOUND 常量）
        return JsonResult.error(
                HttpCodeEnum.RC404.getCode(),
                HttpCodeEnum.RC404.getMsg()
        );
    }

    // -------------------------- 4. 兜底处理：未捕获的通用异常（系统异常） --------------------------
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) // HTTP 状态码 500
    public JsonResult<Void> handleGeneralException(Exception e, HttpServletRequest request) {
        String requestInfo = String.format("[%s %s]", request.getMethod(), request.getRequestURI());
        // 系统异常日志（ERROR级别，记录完整堆栈，便于排查）
        log.error("系统异常 {}: ", requestInfo, e);

        // 生产环境返回脱敏消息（避免暴露系统细节），开发环境可返回具体异常信息
        String errorMsg = "prod".equals(activeProfile)
                ? HttpCodeEnum.RC500.getMsg()
                : e.getMessage();

        // 使用枚举中的 "系统错误" 编码（假设 HttpCodeEnum 有 SYSTEM_ERROR 常量）
        return JsonResult.error(HttpCodeEnum.RC500.getCode(), errorMsg);
    }

    // -------------------------- 辅助配置：环境标识（区分开发/生产） --------------------------
    @Value("${spring.profiles.active:dev}") // 从配置文件读取环境（默认 dev）
    private String activeProfile;
}